package com.website.shiro;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.website.mybatis.dao.RoleDao;
import com.website.mybatis.dao.UserDao;
import com.website.mybatis.entity.SysRole;
import com.website.mybatis.entity.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.AllowAllCredentialsMatcher;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * realm实现
 *
 * @author zhangshuw
 * @date 2018/7/17
 */
@Slf4j
public class MyRealm extends AuthorizingRealm {

    @Autowired
    UserDao userDao;

    @Autowired
    RoleDao roleDao;

    public MyRealm() {
    }

    public MyRealm(CredentialsMatcher matcher) {
        super(matcher);
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        if (principals == null) {
            throw new AuthorizationException("PrincipalCollection method argument cannot be null.");
        }
        SysUser user = (SysUser) getAvailablePrincipal(principals);
        if (user == null) {
            throw new AccountException("用户未登陆");
        }
        SysRole role = roleDao.selectRoleAndPowers(user.getRoleId());
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(Collections.singleton(role.getNote()));
        info.setStringPermissions(role.getPowers().stream().collect(HashSet::new, (set, pow) -> {
            if (StringUtils.isNotBlank(pow.getUrl())) {
                set.add(pow.getUrl());
            }
        }, Set::addAll));
        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();

        if (username == null || upToken.getPassword() == null) {
            log.debug("用户名或密码空");
            throw new AccountException("用户名或密码不能空");
        }
        SysUser user = userDao.selectOne(new QueryWrapper<>(new SysUser(username)));
        if (user == null) {
            throw new UnknownAccountException("未找到该用户信息");
        }
        return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
    }

    @Override
    protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
        CredentialsMatcher cm = getCredentialsMatcher();
        if (cm != null) {
            if (!cm.doCredentialsMatch(token, info)) {
                throw new IncorrectCredentialsException("用户名或密码错误");
            }
        } else {
            throw new AuthenticationException("A CredentialsMatcher must be configured in order to verify " +
                    "credentials during authentication.  If you do not wish for credentials to be examined, you " +
                    "can configure an " + AllowAllCredentialsMatcher.class.getName() + " instance.");
        }
    }
}
